﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Ctrip.Demo.ShenZhou
{
    public class AES_128_CBC
    {
        private static Encoding CHAR_SET = Encoding.UTF8;
        private const string ALGORITHM = "AES/CBC/PKCS7Padding";
        private static byte[] IV = new byte[] { 0xA, 1, 0xB, 5, 4, 0xF, 7, 9, 0x17, 3, 1, 6, 8, 0xC, 0xD, 91 };
        private const string SHENZHOU_DATA_KEY = "zucheios@0703!#$";

        /// <summary>
        /// AES 加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Encrypt(string data, string key = SHENZHOU_DATA_KEY)
        {
            if (string.IsNullOrEmpty(data))
            {
                return data;
            }

            byte[] toEncryptArray = CHAR_SET.GetBytes(data);

            RijndaelManaged rm = new RijndaelManaged();
            rm.IV = IV;
            rm.Key = GetKeyBytes(key);
            rm.Mode = CipherMode.CBC;
            rm.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rm.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            // 兼容 java 解码（c# 无法解码）
            return Convert.ToBase64String(resultArray, 0, resultArray.Length).Replace('+', '-').Replace('/', '_').Replace("==", string.Empty);
        }

        /// <summary>
        ///  AES 解密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string Decrypt(string data, string key = SHENZHOU_DATA_KEY)
        {
            if (string.IsNullOrEmpty(data))
            {
                return data;
            }

            byte[] toEncryptArray = Convert.FromBase64String(data);

            RijndaelManaged rm = new RijndaelManaged();
            rm.IV = IV;
            rm.Key = GetKeyBytes(key);
            rm.Mode = CipherMode.CBC;
            rm.Padding = PaddingMode.PKCS7;

            ICryptoTransform cTransform = rm.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return CHAR_SET.GetString(resultArray);
        }

        private static byte[] GetKeyBytes(string key)
        {
            byte[] keys = CHAR_SET.GetBytes(key);
            byte[] bytes = new byte[128 / 8];

            for (int i = 0; i < bytes.Length; i++)
            {
                if (keys.Length > i)
                {
                    bytes[i] = keys[i];
                }
                else
                {
                    bytes[i] = 0;
                }
            }

            return bytes;
        }
    }
}
